package com.itjcloud.iot.gateway.filter.global;

import com.itjcloud.iot.gateway.model.ApiPermissionProperties;
import com.itjcloud.iot.gateway.model.CommonTokenInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * gateWay权限校验类
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class PermissionsGlobalFilter implements GlobalFilter {

    private final ApiPermissionProperties apiPermissionProperties;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        return Mono.just(exchange).flatMap(this::isRequestPathExcluded).flatMap(excluded -> excluded ?
                        Mono.just(exchange) : authenticate(exchange))
                .flatMap(chain::filter);
    }


    /**
     * 判断是否需要认证接口
     *
     * @param exchange 认证
     * @return 返回数据
     */
    private Mono<ServerWebExchange> authenticate(ServerWebExchange exchange) {
        CommonTokenInfo attribute = exchange.getAttribute(CommonTokenInfo.class.getName());
        if (attribute == null || !attribute.isAuthenticated()) {
            return Mono.error(new AccessDeniedException("Access Denied"));
        } else {
            return Mono.just(exchange);

        }
    }

    /**
     * 判断接口是否是放行接口
     *
     * @param exchange 执行器
     * @return 是否
     */
    private Mono<Boolean> isRequestPathExcluded(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getURI().getPath()).map(path -> apiPermissionProperties.getExcludedPaths().contains(path));
    }

}
